﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using System.Xml;
using System.IO;

namespace SPSource2010.Field
{
    public class FieldManager
    {
        private SPSourceFileInfo _spSourceFileInfo;

        public FieldManager(SPSourceFileInfo spSourceFileInfo)
        {
            _spSourceFileInfo = spSourceFileInfo;
        }

        public void GetField(XmlNode field)
        {
            try
            {
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    using (SPSite site = new SPSite(_spSourceFileInfo.DesignSiteUrl))
                    {
                        using (SPWeb web = site.OpenWeb())
                        {
                            string fieldName = field.Attributes["Name"].Value;
                            SPField sourceField = web.Fields[fieldName];
                            if (sourceField == null)
                            {
                                Utility.WriteMessage("Field does not existing in site!");
                            }
                            else
                            {
                                Utility.WriteMessage("Reverse engineering field: " + fieldName);
                                
                                XmlDocument fieldDocument = new XmlDocument();
                                XmlNode colRootNode = fieldDocument.CreateElement("Elements");
                                fieldDocument.AppendChild(colRootNode);

                                GenerateFieldXml(sourceField, colRootNode);

                                XmlAttribute colNameSpace = fieldDocument.CreateAttribute("xmlns");
                                colNameSpace.Value = Constants.SharePointXmlNamespace;
                                colRootNode.Attributes.Append(colNameSpace);

                                string fieldFileName = fieldName + ".Fields.xml";
                                fieldDocument.Save(_spSourceFileInfo.SPSourceFileDirectoryInfo.FullName + "\\" + fieldFileName);


                                if (!_spSourceFileInfo.OverrideFeatureDirectoryCheck)
                                {
                                    FeatureManager.AddElementManifestToFeature(
                                        new FileInfo(_spSourceFileInfo.SPSourceFileDirectoryInfo.FullName + "\\" + fieldFileName));
                                }
                            }
                        }
                    }
                });
            }
            catch (Exception ex)
            {
                Utility.WriteError(ex.ToString());
                throw;
            }
        }

        public void GenerateFieldXml(SPField sourceField, XmlNode colRootNode)
        {
            string sourceFieldSchema = sourceField.SchemaXml;
            colRootNode.InnerXml += sourceFieldSchema;

            XmlNodeList columnFields = colRootNode.SelectNodes("//Field");
            removeUneededAttributes(columnFields);
            modifyAttributes(columnFields);
        }

        public void modifyAttributes(XmlNodeList nodeList)
        {
            foreach (XmlNode columnField in nodeList)
            {
                XmlAttribute sourceID = columnField.Attributes["SourceID"];
                sourceID.Value = "http://schemas.microsoft.com/sharepoint/v3";

                //need to modify as outputs in incorrect format from schemaXML!
                if (columnField.Attributes["UserSelectionMode"] != null)
                {
                    XmlAttribute userSelectionMode = columnField.Attributes["UserSelectionMode"];
                    userSelectionMode.Value = (userSelectionMode.Value == "PeopleOnly" ? "0" : "1");
                }
            }
        }

        List<string> validChildNodes = new List<string> { "FieldRefs", "CHOICES", "DefaultFormula", "MAPPINGS", "DisplayPattern", "DisplayBidiPattern", "Default", "Formula" };
        public void removeUneededAttributes(XmlNodeList nodeList)
        {
            //NOTE: this will get rid of Customization element that is not valid
            foreach (XmlNode columnField in nodeList)
            {
                for(int i = 0; i < columnField.ChildNodes.Count; i++)
                {
                    bool valid = false;
                    foreach (string validChildNode in validChildNodes)
                    {
                        if (validChildNode == columnField.ChildNodes[i].Value)
                        {
                            valid = true;
                            break;
                        }
                    }
                    if (!valid)
                        columnField.RemoveChild(columnField.ChildNodes[0]);
                }

                XmlAttribute customization = columnField.Attributes["Customization"];
                columnField.Attributes.Remove(customization);

                XmlAttribute Version = columnField.Attributes["Version"];
                columnField.Attributes.Remove(Version);

                XmlAttribute PITarget = columnField.Attributes["PITarget"];
                columnField.Attributes.Remove(PITarget);

                XmlAttribute PrimaryPITarget = columnField.Attributes["PrimaryPITarget"];
                columnField.Attributes.Remove(PrimaryPITarget);

                XmlAttribute PIAttribute = columnField.Attributes["PIAttribute"];
                columnField.Attributes.Remove(PIAttribute);

                XmlAttribute PrimaryPIAttribute = columnField.Attributes["PrimaryPIAttribute"];
                columnField.Attributes.Remove(PrimaryPIAttribute);

                XmlAttribute Aggregation = columnField.Attributes["Aggregation"];
                columnField.Attributes.Remove(Aggregation);

                XmlAttribute Node = columnField.Attributes["Node"];
                columnField.Attributes.Remove(Node);

                XmlAttribute WebId = columnField.Attributes["WebId"];
                columnField.Attributes.Remove(WebId);
            }
        }
    }
}
